﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace Thrift.Utility
{
    internal class ConfigHelper
    {
        private static string ThriftConfigFilePath = ConfigurationManager.AppSettings["ThriftConfigFilePath"] ?? "Configuration/Thrift.Config";

        public static ThriftConfig ThriftConfig
        {
            get
            {
                return CacheHelper.GetWithLocalCache<ThriftConfig>("Thrift_ThriftConfig", LoadThriftConfig);
            }
        }

        public static List<ServiceConfig> GetServiceConfigs()
        {
            List<ServiceConfig> services = new List<ServiceConfig>(ThriftConfig.ServiceArray.Count);
            foreach(var sc in ThriftConfig.ServiceArray)
            {
                if (!services.Exists(service => service.Name.ToUpper() == sc.Name.ToUpper()))
                {
                    //IP验证
                    if (IsIPV4Address(sc.IP))
                    {
                        services.Add(sc);
                    }
                    else
                    {
                        throw new ThriftException(string.Format("The Service Config Named \"{0}\",Which's IP({1}) Is Not Valid!", sc.Name, sc.IP));
                    }                    
                }
                else
                {
                    throw new ThriftException(string.Format("There Is A Service Config Named \"{0}\",Please Check Service Config File!", sc.Name));
                }
            }
            if (services.Count==0)
            {
                throw new ThriftException("There Is No Specific Service!");
            }
            return services;
        }

        private static ThriftConfig LoadThriftConfig()
        {
            string path = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, ThriftConfigFilePath);
            if (File.Exists(path))
            {
                return SerializeHelper.LoadFromXml<ThriftConfig>(path);
            }
            throw new ThriftException(string.Format("Not Found Thrift Config File \"{0}\"", path));
        }

        private static bool IsIPV4Address(string input)
        {
            return Regex.IsMatch(input, @"^((?:(?:25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))\.){3}(?:25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d))))$");
        }
    }


    [Serializable]
    public class ThriftConfig
    {
        /// <summary>
        /// 监视器类型
        /// 用于监视连接池运行状态
        /// 继承自ITriftFactoryMonitor类
        /// </summary>
        [XmlElement]
        public string MonitorType { get; set; }
        
        [XmlArrayItem("Service")]
        public List<ServiceConfig> ServiceArray { get; set; }
    }

    [Serializable]
    public class ServiceConfig
    {
        [XmlAttribute]
        public string Name { get; set; }

        [XmlAttribute]
        public string IP { get; set; }

        [XmlAttribute]
        public int Port { get; set; }

        [XmlAttribute]
        public int MaxActive { get; set; }

        [XmlAttribute]
        public int MaxIdle { get; set; }

        [XmlAttribute]
        public int MinIdle { get; set; }

        /// <summary>
        /// 连接池等待连接时间
        /// 单位毫秒
        /// 超时记日志还是通知谁更改连接池配置
        /// </summary>
        [XmlElement, DefaultValue(1000)]
        public int WaitingTimeout { get; set; }
    }
}
